package com.jk.controller;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import com.jk.entity.OrderEntity;
import com.jk.entity.ProductEntity;
import com.jk.entity.SecondKillEntity;
import com.jk.service.SecKillService;
import com.jk.utils.MsgUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;

@RequestMapping("second")
@RestController
@CrossOrigin(origins = "*")
public class SecondKillController {

//    private int totalNum = 10;//总商品数量
//
//    private int lockTimeOut = 3;//锁过期时间3秒
//
//    private int userPatient = 30000;//用户抢购的模拟时间（毫秒）
//
//    private int userNum = 100000;//抢购人数


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SecKillService secKillService;

    @RequestMapping("findSec")
    public List<SecondKillEntity> findSec(SecondKillEntity secondKillEntity){
        return secKillService.findSec(secondKillEntity);
    }

    @RequestMapping("kill")
    public Map kill(OrderEntity product){
        Integer id = product.getProId();
        String o = (String) redisTemplate.opsForValue().get("----" + id);

        if (o==null){
            int num = secKillService.findCount(id);
            redisTemplate.opsForValue().set("----" +id,String.valueOf(num));
            o = String.valueOf(num);
        }


       String uuid = UUID.randomUUID().toString();

        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock"+uuid, o,3,TimeUnit.SECONDS);//设置锁过期时间，防止死锁
        int newCount= Integer.parseInt(o);
        if (lock) {
                //首先查看总库存，如果为0，则返回null
                if (newCount < 1) {
                    redisTemplate.delete("----" +id);
                    return MsgUtil.returnMsg(250,"商品已抢光",null);

                }
//                //模拟用户生成订单时间
//                try {
//                    TimeUnit.SECONDS.sleep(1);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                 newCount--;

                //使用LUA脚本执行原子操作，避免锁误删
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
                redisScript.setScriptText(script);

                // 设置一下返回值类型 为Long
                // 因为删除判断的时候，返回的0,给其封装为数据类型。如果不封装那么默认返回String 类型，
                // 那么返回字符串与0 会有发生错误。
                redisScript.setResultType(Long.class);
                // 第一个要是script 脚本 ，第二个需要判断的key，第三个就是key所对应的值。
                redisTemplate.execute(redisScript, Arrays.asList("-"+id), String.valueOf(newCount));

                redisTemplate.opsForValue().decrement("----"+id);
                redisTemplate.opsForValue().decrement("lock"+uuid);

                //生成订单

                secKillService.saveOrder(product);
                secKillService.buy(product.getProId());

                return MsgUtil.returnMsg(200,"抢到啦",null);
            } else {
                return MsgUtil.returnMsg(251,"请稍等",null);
            }
    }

    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //设置 value 的序列化方式为 JOSON
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        //设置 key 的序列化方式为 String
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }



    @RequestMapping("findSecfour")
    public List<SecondKillEntity> findSecfour(){
        return secKillService.findSecfour();
    }

    @RequestMapping("addKill")
    public void addKill(SecondKillEntity secondKill){
        secKillService.addKill(secondKill);
    }


    @RequestMapping("findSecAll")
    public List<SecondKillEntity> findSecAll(SecondKillEntity secondKill){
        return  secKillService.findSecAll(secondKill);
    }

    @RequestMapping("delSecPro")
    private void delSecPro(Integer id){
        secKillService.delSecPro(id);
    }


    @RequestMapping("buyPro")
    public void buyPro(OrderEntity product){
        secKillService.saveOrder(product);
        secKillService.buy(product.getProId());
    }






















//    @GetMapping("monitor")
//    public List<String> monitor() {
//        //初始化抢购用户
//        List<String> users = initUsers();
//        //抢购成功用户结果表
//        List<String> winners = new ArrayList<>();
//
//        users.parallelStream().forEach(user -> {
//            //用户尝试抢购
//            String currentUser = rob(user);
//            //如果抢购成功，则将用户放入结果表
//            if (!StringUtils.isEmpty(currentUser)) {
//                winners.add(currentUser);
//            }
//        });
//
//        return winners;
//
//
//    }
//    public String rob(String user) {
//        //用户开抢时间
//        long startTime = System.currentTimeMillis();
//
//        //模拟用户持续抢
//        while ((startTime + userPatient) >= System.currentTimeMillis()) {
//            //首先查看总库存，如果为0，则返回null
//            if (totalNum < 1) {
//                return null;
//            }
//
//            String uuid = UUID.randomUUID().toString();
//            Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, lockTimeOut, TimeUnit.SECONDS);//设置锁过期时间，防止死锁
//            //获取锁成功
//            if (lock) {
//                //首先查看总库存，如果为0，则返回null
//                if (totalNum < 1) {
//                    return null;
//                }
//                //模拟用户生成订单时间
//                try {
//                    TimeUnit.SECONDS.sleep(1);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//
////                log.info("用户 {} 抢购成功", user);
//                totalNum--;
//
//
//                //使用LUA脚本执行原子操作，避免锁误删
//                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//                DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//                redisScript.setScriptText(script);
//
//                // 设置一下返回值类型 为Long
//                // 因为删除判断的时候，返回的0,给其封装为数据类型。如果不封装那么默认返回String 类型，
//                // 那么返回字符串与0 会有发生错误。
//                redisScript.setResultType(Long.class);
//                // 第一个要是script 脚本 ，第二个需要判断的key，第三个就是key所对应的值。
//                redisTemplate.execute(redisScript, Arrays.asList("lock"), uuid);
//                return user;
//            } else {
////                log.error("获取锁失败！（没抢到）");
//            }
//        }
//        return null;
//
//    }
//
//    List<String> initUsers() {
//        List<String> result = new ArrayList<>();
//        //这里简单的用数字代指用户
//        for (int i = 1; i <= userNum; i++) {
//            result.add(String.valueOf(i));
//        }
//
//        return result;
//    }


}
